package com.tabnet.dao.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

import com.tabnet.beans.produit.Accessoire;
import com.tabnet.beans.produit.Categorie;
import com.tabnet.beans.produit.Option;
import com.tabnet.beans.produit.ProduitCMD;
import com.tabnet.dao.DAOAccessoireCMD;
import com.tabnet.dao.DAOException;
import com.tabnet.dao.DAOFactory;
import com.tabnet.dao.DAOOptionCMD;
import com.tabnet.dao.DAOProduitCMD;
import com.tabnet.dao.DAOUtilitaire;

/**
 * <p>Interface DAOProduitCMD</p>
 * @author Corentin, Cyril, Neven, Anabella
 * */
public class ProduitCMDDAOImpl implements DAOProduitCMD {
	
	private static final String SQL_SELECT_BY_ID  		= "SELECT * FROM ProduitCMD WHERE ID_PRDC = ?";
	//private static final String SQL_INSERT		  		= "INSERT INTO ProduitCMD(Ref_PRDC, Description_PRDC, NomPCMD, PuPCMD, CAT_Ref) VALUES (?,?,?,?,?)";
	private static final String SQL_INSERT		  		= "INSERT INTO ProduitCMD VALUES (?,?,?,?,?,?)";
	//private static final String SQL_UPDATE		  		= "UPDATE ProduitCMD SET Description_PRDC=?, NomPCMD=?, PuPCMD=?, CAT_Ref=? WHERE ID_PRDC = ?";
	private static final String SQL_DELETE		  		= "DELETE FROM ProduitCMD WHERE ID_PRDC = ?";
	private static final String SQL_SELECT_LAST			= "SELECT MAX(ID_PRDC) AS ID_PRDC FROM ProduitCMD";
	
	private DAOAccessoireCMD _DaoAccessoireCMD;
	private DAOOptionCMD _DaoOptionCMD;
	private DAOFactory _DaoFactory;
	
	public ProduitCMDDAOImpl( DAOFactory pDaoFactory ) {
        this._DaoFactory = pDaoFactory;
        this._DaoAccessoireCMD = pDaoFactory.getAccessoireCMDDAO();
        this._DaoOptionCMD = pDaoFactory.getOptionCMDDAO();
    }
	
	/**
     * <p>Fonction map<br />
     * Simple méthode utilitaire permettant de faire la correspondance (le
     * mapping) entre une ligne issue de la table des produits commander (un ResultSet) et
     * un bean ProduitCMD.</p>
     * @param resultSet : objet ResultSet
	 * @return objet ProduitCMD
	 * @throws SQLException
     */
    private ProduitCMD map( ResultSet resultSet ) throws SQLException {
    	ProduitCMD oProduitCMD = new ProduitCMD();
    	oProduitCMD.setId(resultSet.getInt("ID_PRDC"));
    	oProduitCMD.setRef(resultSet.getString("Ref_PRDC"));
    	oProduitCMD.setDescription(resultSet.getString("Description_PRDC"));
    	oProduitCMD.setNom(resultSet.getString("NomPCMD"));
    	oProduitCMD.setPu(resultSet.getDouble("PuPCMD"));
    	
    	
		try {
			// récupération de la catégorie avec la DAO
    		Categorie oCategorie = this._DaoFactory.getCategorieDAO().trouverCategorie(resultSet.getString("CAT_Ref"));
			oProduitCMD.setCategorie(oCategorie);
		

			// récupération des options avec la DAO
			Map<String, Option> mapOptions = this._DaoOptionCMD.getOptions(oProduitCMD.getId());
			oProduitCMD.setLstOption(mapOptions);
			
			// récupération des accessoires avec la DAO
			Map<String, Accessoire> mapAccessoires = this._DaoAccessoireCMD.getAccessoires(oProduitCMD.getId());
			oProduitCMD.setLstAccessoire(mapAccessoires);
    	
		}
		catch (DAOException e) {
			e.printStackTrace();
		}
		
        return oProduitCMD;
    }
    
    /**
     * <p>Fonction getLastId<br />
     * Retourne le dernier id d'un produit commander</p>
     * @throws SQLException
     * @return un entier
     * */
    private int getLastId() throws SQLException, DAOException {
		Connection oConnection = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet resultSet = null;
        
        int id = 0;

        try {
        	oConnection = this._DaoFactory.getConnection();
        	
            // récupération des accessoires commandes
        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnection, SQL_SELECT_LAST, false);
            resultSet = oPreparedStatement.executeQuery();
            
            if ( resultSet.next() )
            	id = resultSet.getInt("ID_PRDC");
        }
        catch ( SQLException e ) {
            throw new DAOException(e);
        }
        finally {
            DAOUtilitaire.fermeturesSilencieuses( resultSet, oPreparedStatement, oConnection );
        }

        return id;
    }
    
	@Override
	public void addProduitCMD(ProduitCMD pProduit) throws DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet valeursAutoGenerees = null;
        boolean execAdd = false;
        
        try {
        	oConnexion = this._DaoFactory.getConnection();
            
        	pProduit.setId(this.getLastId() + 1);
        	
            //insertion du produit
        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_INSERT, true,
        			pProduit.getId(), pProduit.getRef(), pProduit.getDescription(), pProduit.getNom(),
        			pProduit.getPu(), pProduit.getCategorie().getRef() );
        	            
            if ( oPreparedStatement.executeUpdate() == 0 )
                throw new DAOException( "Échec de la création du produit commander, aucune ligne ajoutée dans la table." );

        	execAdd = true;
        	
            //Liaison des données
        	this._DaoAccessoireCMD.addAccessoires(pProduit);
        	this._DaoOptionCMD.addOptions(pProduit);
        	
        }
        catch ( SQLException e ) {
        	if(execAdd)
        		this.delProduitCMD(pProduit.getId());
        	
            throw new DAOException( e );
        }
        finally {
        	 DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, oPreparedStatement, oConnexion );
        }
	}

	@Override
	public void updProduitCMD(ProduitCMD pProduit) throws DAOException {
		// TODO Auto-generated method stub
	}

	@Override
	public void delProduitCMD(int pIdProduitCMD) throws DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet valeursAutoGenerees = null;
        
        try {
        	oConnexion = this._DaoFactory.getConnection();

            //suppression des options et accessoires
        	this._DaoAccessoireCMD.delAccessoires(pIdProduitCMD);
        	this._DaoOptionCMD.delOptions(pIdProduitCMD);
            
            //suppression du produit commander
        	oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_DELETE, true, pIdProduitCMD );
        	            
            if ( oPreparedStatement.executeUpdate() == 0 )
                throw new DAOException( "Échec de la suppression du produit commander, aucune ligne ajoutée dans la table." );

        }
        catch ( SQLException e ) {
            throw new DAOException( e );
        }
        finally {
        	 DAOUtilitaire.fermeturesSilencieuses( valeursAutoGenerees, oPreparedStatement, oConnexion );
        }
		
	}

	@Override
	public ProduitCMD foundProduitCMD(int pIdProduitCMD) throws DAOException {
		Connection oConnexion = null;
        PreparedStatement oPreparedStatement = null;
        ResultSet resultSet = null;
        ProduitCMD oProduitCMD = new ProduitCMD();
        
        try {
            /* Récupération d'une connexion depuis la Factory */
            oConnexion = this._DaoFactory.getConnection();
           
            oPreparedStatement = DAOUtilitaire.initialisationRequetePreparee( oConnexion, SQL_SELECT_BY_ID, false, pIdProduitCMD );
            
            resultSet = oPreparedStatement.executeQuery();
            /* Parcours de la ligne de données retournée dans le ResultSet */
            if ( resultSet.next() ) 
            	oProduitCMD = this.map(resultSet);
        }
        catch ( SQLException e ) {
            throw new DAOException( e );
        }
        finally {
            DAOUtilitaire.fermeturesSilencieuses( resultSet, oPreparedStatement, oConnexion );
        }
        
        return oProduitCMD;
	}

}
